//	 Copyright 2011 Elian ORIOU
//
//   Licensed under the Apache License, Version 2.0 (the "License");
//   you may not use this file except in compliance with the License.
//   You may obtain a copy of the License at
//
//       http://www.apache.org/licenses/LICENSE-2.0
//
//   Unless required by applicable law or agreed to in writing, software
//   distributed under the License is distributed on an "AS IS" BASIS,
//   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//   See the License for the specific language governing permissions and
//   limitations under the License.

package org.eo.geomapper.renderer;

import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.List;

import javax.imageio.ImageIO;

import org.eo.geomapper.objects.GeoLine;
import org.eo.geomapper.objects.GeoPoint;
import org.eo.geomapper.objects.GeoPolygon;
import org.eo.geomapper.objects.ILayer;
import org.eo.geomapper.objects.IObject;

/**
 * The GeoMapper renderer, it generates the image according to GIS informations
 * provided by user
 * 
 * @author Elian ORIOU
 * 
 */

public class GeoMapperRenderer {

	private BufferedImage image;
	private List<ILayer> layers;

	public GeoMapperRenderer() {
	}

	/**
	 * Generates the image
	 * 
	 * @param layers
	 *            layers to be used for image generation
	 * @param width
	 *            the generated image width
	 * @param height
	 *            the generated image height
	 * @return the generated image
	 */

	public BufferedImage generateImage(List<ILayer> layers, int width,
			int height) {
		this.layers = layers;
		image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);

		Graphics2D g = image.createGraphics();
		initImageState(g);

		for (ILayer l : this.layers) {
			g.setColor(l.getColor());
			for (IObject object : l.getObjects()) {
				switch (l.getObjectType()) {
				case POINT:
					GeoPoint p = (GeoPoint) object;
					g.fillOval(p.getCoordX(), p.getCoordY(), 5, 5);
					g.drawString(p.getName(), p.getCoordX(), p.getCoordY() - 5);
					break;
				case LINE:
					GeoLine line = (GeoLine) object;
					for (int i = 0; i < line.getPoints().size() - 1; i++) {
						GeoPoint geopoint = line.getPoints().get(i);
						GeoPoint nextgeopoint = line.getPoints().get(i + 1);
						g.drawLine(geopoint.getCoordX(), geopoint.getCoordY(),
								nextgeopoint.getCoordX(), nextgeopoint
										.getCoordY());
					}
					if (line.getName() != null) {
						g.drawString(line.getName(), (line.getPoints().get(0)
								.getCoordX() + line.getPoints().get(
								line.getLength() - 1).getCoordY()) / 2, ((line
								.getPoints().get(0).getCoordY() + line
								.getPoints().get(line.getLength() - 1)
								.getCoordY()) / 2) - 10);
					}
					break;
				case POLYGON:
					GeoPolygon polygon = (GeoPolygon) object;
					int[] x = new int[polygon.getLength()];
					int[] y = new int[polygon.getLength()];
					for (int i = 0; i < polygon.getPoints().size(); i++) {
						GeoPoint geopoint = polygon.getPoints().get(i);
						x[i] = geopoint.getCoordX();
						y[i] = geopoint.getCoordY();
					}
					g.fillPolygon(x, y, polygon.getLength());
					if (polygon.getName() != null) {
						g
								.drawString(
										polygon.getName(),
										(polygon.getPoints().get(0).getCoordX() + polygon
												.getPoints()
												.get(polygon.getLength() - 1)
												.getCoordY()) / 2,
										((polygon.getPoints().get(0)
												.getCoordY() + polygon
												.getPoints()
												.get(polygon.getLength() - 1)
												.getCoordY()) / 2) - 10);
					}
					break;
				}
			}
		}
		return image;
	}

	/**
	 * Initializes the image generation configuration
	 * 
	 * @param g
	 *            The graphics object (drawing utility)
	 */

	private void initImageState(Graphics2D g) {
		/* Draws an image with a white background */
		g.setBackground(Color.WHITE);
		g.clearRect(0, 0, image.getWidth(), image.getHeight());
	}

	/**
	 * Saves the image
	 * 
	 * @param outputPath
	 *            The image output path
	 * @param extension
	 *            The image extension
	 * @throws IOException
	 */

	public void saveImage(String outputPath, String extension)
			throws IOException {
		File imageFile = new File(outputPath);
		ImageIO.write(image, extension, imageFile);
	}
}
